package com.maschinenstuermer.profiler.trace.presentation;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.TreeItem;

/**
 * Painter which paints the class and method part name of a method signature
 * bold.
 * 
 * @author km
 */
public class MethodNamePainter implements Listener {
	private static final Pattern METHOD_PATTERN = Pattern
			.compile("(.*\\.)(.*\\..*\\(.*\\)(:.*)?)");

	@Override
	public void handleEvent(Event event) {
		final int index = event.index;
		if (index == 0) {
			final Item item = (Item) event.item;
			final String text = item.getText();
			final Matcher matcher = METHOD_PATTERN.matcher(text);
			if (matcher.matches()) {
				final GC gc = event.gc;
				final Rectangle bounds = event.getBounds();
				gc.fillRectangle(bounds);

				final TextLayout textLayout = new TextLayout(gc.getDevice());
				textLayout.setText(text);

				final Font font = gc.getFont();
				final TextStyle packageTextStyle = new TextStyle(font, gc
						.getForeground(), null);
				final String packageName = matcher.group(1);
				textLayout.setStyle(packageTextStyle, 0,
						packageName.length() - 1);

				final Font boldFont = createBoldFont(font);
				final TextStyle classAndMethodTextStyle = new TextStyle(
						boldFont, gc.getForeground(), null);
				textLayout.setStyle(classAndMethodTextStyle, packageName
						.length(), text.length() - 1);
				final int textX = drawImage(event, item);
				textLayout.draw(gc, textX, event.y + 2);

				boldFont.dispose();
				textLayout.dispose();
			}
		}
	}
	
	private int drawImage(final Event event, final Item item) {
		int imageOffset = event.x;
		if (item instanceof TreeItem) {
			final TreeItem treeItem = (TreeItem) item;
			final Image image = treeItem.getImage(0);
			final Rectangle bounds = treeItem.getImageBounds(0);
			
			imageOffset = drawItemImage(event, imageOffset, bounds, image);
		}
		else if (item instanceof TableItem) {
			final TableItem treeItem = (TableItem) item;
			final Image image = treeItem.getImage(0);
			final Rectangle bounds = treeItem.getImageBounds(0);
			
			imageOffset = drawItemImage(event, imageOffset, bounds, image);			
		}
		return imageOffset;
	}

	private int drawItemImage(final Event event, int imageOffset,
			final Rectangle bounds, final Image image) {
		if (image != null) {
			final GC gc = event.gc;
			final Rectangle imageBounds = image.getBounds();
			gc.drawImage(image, 0, 0, imageBounds.width, imageBounds.height, 
					bounds.x, bounds.y, bounds.width, bounds.height);
			imageOffset = bounds.x + bounds.width + 2;
		}
		return imageOffset;
	}

	private Font createBoldFont(final Font font) {
		FontData[] fontDatas = font.getFontData();
		for (FontData fontData : fontDatas) {
			fontData.setStyle(SWT.BOLD);
		}
		Font boldFont = new Font(font.getDevice(), fontDatas);
		return boldFont;
	}

}
